/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : hi_syslink_cmd.c
 * Author        : joki.zhu
 * Date          : 2020-07-28
 *
 * Record        :
 * 1.Date        : 2020-07-28
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include "hi_syslink_cmd.h"
#include "hi_hal_syslink.h"
#include "hi_syslink.h"
#include "securec.h"
#include "shell.h"
#include "hi_appcomm_log.h"
#include "hi_appcomm.h"
#include "DevSocSub.h"

#define SYSLINK_MAX_CMD_TEXT_LEN 128

static HI_S32 SYSLINK_CMD_SysLinkInit(HI_S32 argc, HI_CHAR **argv)
{
    return HI_HAL_SYSLINK_Init();
}

static HI_S32 SYSLINK_CMD_SysLinkDeinit(HI_S32 argc, HI_CHAR **argv)
{
    return HI_HAL_SYSLINK_Deinit();
}

static HI_S32 SYSLINK_CMD_SysLinkBootInfo(HI_S32 argc, HI_CHAR **argv)
{
    return HI_HAL_SYSLINK_GetBootInfo();
}

static HI_S32 SYSLINK_CMD_SendCmdToWifi(HI_S32 argc, HI_CHAR **argv)
{
    if (argc < 2) { /* 2:argc */
        MLOGE("please input cmd str and [qos].\nsuch as:[s sendcmd standby 0].\n");
        return HI_SUCCESS;
    }
    HAL_SYSLINK_MsgQos qos;
    if (argc > 1) {
        if (strcmp(argv[1], "1") == 0) {
            qos = HAL_SYSLINK_MSG_QOS_WITH_RESP;
        } else {
            qos = HAL_SYSLINK_MSG_QOS_DIRECTLY;
        }
    } else {
        qos = HAL_SYSLINK_MSG_QOS_DIRECTLY;
    }

    HI_S32 len = strlen(argv[0]) + 1;
    HI_CHAR *msg = (HI_CHAR *)malloc(len);
    if (msg == HI_NULL) {
        MLOGE("malloc failed.\n");
        return HI_FAILURE;
    }

    errno_t err = memset_s(msg, len, 0, len);
    if (err != EOK) {
        MLOGE("memset_s failed(0x%x).\n", err);
        free(msg);
        msg = HI_NULL;
        return HI_FAILURE;
    }

    HI_S32 ret = snprintf_s(msg, len, len - 1, "%s", argv[0]);
    if (ret < 0) {
        MLOGW("snprintf_s failed\n");
        free(msg);
        msg = HI_NULL;
        return HI_FAILURE;
    }

    ret = HI_HAL_SYSLINK_SendTextMsgToWifi(msg, len, qos);
    HI_APPCOMM_LOG_IF_EXPR_FALSE(ret == HI_SUCCESS, "HI_SAMPLE_SYSLINK_SendMsgToWifi");

    free(msg);
    msg = HI_NULL;

    MLOGP("send cmd:%s to camera, len:%d, qos:%d.\n", msg, len, qos);

    return HI_SUCCESS;
}

static hi_syslink_tty_type str_to_tty_type(const hi_char *tty_name)
{
    if (strcmp(tty_name, "shell") == 0) {
        return HI_SYSLINK_TTY_SHELL;
    } else if (strcmp(tty_name, "at") == 0) {
        return HI_SYSLINK_TTY_AT;
    } else if (strcmp(tty_name, "diag") == 0) {
        return HI_SYSLINK_TTY_DIAG;
    } else if (strcmp(tty_name, "sigma") == 0) {
        return HI_SYSLINK_TTY_SIGMA;
    } else {
        return HI_SYSLINK_TTY_BUTT;
    }
}

static hi_u32 SYSLINK_CMD_EnableTty(hi_u32 argc, hi_char **argv)
{
    if (argc < 1) {
        printf("example: enabletty shell/at/diag/sigma\n");
        return 0;
    }
    hi_syslink_tty_type type = str_to_tty_type(argv[0]);
    if (type == HI_SYSLINK_TTY_BUTT) {
        printf("example: enabletty shell/at/diag/sigma\n");
        return 0;
    }

    return hi_syslink_enable_tty(type, HI_TRUE);
}

static hi_u32 SYSLINK_CMD_DisableTty(hi_u32 argc, hi_char **argv)
{
    if (argc < 1) {
        printf("example: disabletty shell/at/diag/sigma\n");
        return 0;
    }
    hi_syslink_tty_type type = str_to_tty_type(argv[0]);
    if (type == HI_SYSLINK_TTY_BUTT) {
        printf("example: disabletty shell/at/diag/sigma\n");
        return 0;
    }

    return hi_syslink_enable_tty(type, HI_FALSE);
}


static hi_u32 SYSLINK_CMD_AttachTty(hi_u32 argc, hi_char **argv)
{
    if (argc < 1) {
        printf("example: attachtty shell/at/diag/sigma\n");
        return 0;
    }
    hi_syslink_tty_type type = str_to_tty_type(argv[0]);
    if (type == HI_SYSLINK_TTY_BUTT) {
        printf("example: attachtty shell/at/diag/sigma\n");
        return 0;
    }

    return hi_syslink_attach_tty(type);
}

static hi_u32 SYSLINK_CMD_SetLogLevel(hi_u32 argc, hi_char **argv)
{
    if (argc < 1) {
        printf("example: setloglevel 2\n");
        return 0;
    }

    return hi_syslink_set_log_level(atoi(argv[0]));
}

static hi_u32 SYSLINK_CMD_GetLogLevel(hi_u32 argc, hi_char **argv)
{
    hi_syslink_log_level log_level;

    hi_syslink_get_log_level(&log_level);
    printf("log_level %d\n", log_level);

    return 0;
}

static hi_u32 SYSLINK_CMD_SetWifiConnect(hi_u32 argc, hi_char **argv)
{
    if (argc < 1) {
        printf("[ssid] [password]\n");
        return -1;
    }
    
    HI_SYSLINK_PARM_S stSendMsg;
    HI_SYSLINK_WIFI_ATTR stWifiAttr = {0};
    
    memset(&stSendMsg, 0, sizeof(stSendMsg));
    stSendMsg.u32MsgId = HI_SYSLINK_MSGID_S2W_SET_WIFI_CONNECT;

    if (argc == 1) {
        snprintf(stWifiAttr.ssid, sizeof(stWifiAttr.ssid), "%s", argv[0]);
        stWifiAttr.auth = HI_SYSLINK_WIFI_SECURITY_OPEN;
    } else if (argc == 2) {
        snprintf(stWifiAttr.ssid, sizeof(stWifiAttr.ssid), "%s", argv[0]);
        snprintf(stWifiAttr.pwd, sizeof(stWifiAttr.pwd), "%s", argv[1]);
        stWifiAttr.auth = HI_SYSLINK_WIFI_SECURITY_WPAPSK_WPA2PSK_MIX;
    }

    printf("connet wifi ssid: %s pwd:%s\n", stWifiAttr.ssid, stWifiAttr.pwd);
    
    memcpy(stSendMsg.data, &stWifiAttr, sizeof(stWifiAttr));
    stSendMsg.dataLen = sizeof(stWifiAttr);
    
    HI_HAL_SYSLINK_SendMsgToWifiAsync(&stSendMsg);

    return 0;
}

static hi_u32 SYSLINK_CMD_SetWifiDisConnect(hi_u32 argc, hi_char **argv)
{
    wifisoc_set_wifi_disconnect();
    return 0;
}


static hi_u32 SYSLINK_CMD_GetWifiStatus(hi_u32 argc, hi_char **argv)
{
    HI_SYSLINK_PARM_S stSendMsg = {0};
    HI_SYSLINK_PARM_S stWaitMsg = {0};
    HI_SYSLINK_WIFI_ATTR stWifiAttr = {0};
    HI_SYSLINK_WIFI_STATUS stWifiStatus = {0};
    
    stSendMsg.u32MsgId = HI_SYSLINK_MSGID_S2W_GET_WIFI_STATUS;
    stWaitMsg.dataLen = sizeof(stWifiStatus);
    HI_S32 ret = HI_HAL_SYSLINK_SendMsgToWifiSync(&stSendMsg, &stWaitMsg, 3000);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_HAL_SYSLINK_SendMsgToWifiSync fail ret %d\n", ret);
        return ret;
    }
    memcpy(&stWifiStatus, stWaitMsg.data, stWaitMsg.dataLen);
    
    MLOGD("ssid:%s rssi:%d state:%d\n", stWifiStatus.ssid, stWifiStatus.rssi, stWifiStatus.state);
    
    return 0;
}


static hi_u32 SYSLINK_CMD_SetLedOn(hi_u32 argc, hi_char **argv)
{
    SocSubSetLedState(0x3);
    return 0;
}

static hi_u32 SYSLINK_CMD_SetLedOff(hi_u32 argc, hi_char **argv)
{
    SocSubSetLedState(0x0);
    return 0;
}

static hi_u32 SYSLINK_CMD_GetVer(hi_u32 argc, hi_char **argv)
{
    char version[16] = {0};    

    SocSubGetVersion(version);
    
    return 0;
}

static hi_u32 SYSLINK_CMD_GetBatStatus(hi_u32 argc, hi_char **argv)
{
    char version[16] = {0};    

    BATTERY_STATUS_S stBatStatus = {0};
    SocSubGetBatteryStatus(&stBatStatus);
    
    LOGD("capacity:%d isLowBatState:%d\n", stBatStatus.capacity, stBatStatus.isLowBatState);
    
    return 0;
}

static hi_u32 SYSLINK_CMD_SetPirState(hi_u32 argc, hi_char **argv)
{
    int state = atoi(argv[0]);

    LOGD("set pir state: %d\n", state);
    SocSubSetPirSwitch(state);
    
    return 0;
}

static hi_u32 SYSLINK_CMD_GetPirState(hi_u32 argc, hi_char **argv)
{
    int state = 0;

    SocSubGetPirSwitch(&state);
    LOGD("get pir state: %d\n", state);
    
    return 0;
}

static hi_u32 SYSLINK_CMD_SetSystemMode(hi_u32 argc, hi_char **argv)
{
    int sysmode = atoi(argv[0]);

    LOGD("set system mode: %d\n", sysmode);
    SocSubSetSystemMode((HI_SYSLINK_SYS_MODE)sysmode);
    
    return 0;
}


static hi_u32 SYSLINK_CMD_SetDateTime(hi_u32 argc, hi_char **argv)
{
    SYSTEM_TIME stSysTime = {0};

    stSysTime.year = 2020;
    stSysTime.month = 8;
    stSysTime.day = 5;
    stSysTime.hour = 9;
    stSysTime.minute = 30;
    stSysTime.second = 55;

    SocSubSetTime(stSysTime);
    
    return 0;
}

static hi_u32 SYSLINK_CMD_GetDateTime(hi_u32 argc, hi_char **argv)
{
    SYSTEM_TIME stSysTime = {0};

    SocSubGetTime(&stSysTime);
    
    return 0;
}

typedef struct {
    HI_U8 testTitle[SYSLINK_MAX_CMD_TEXT_LEN];
    HI_S32 (*cmdFunc)(HI_U32 argc, HI_CHAR **argv);
} SAMPLE_SYSLINK_CmdAttr;

SAMPLE_SYSLINK_CmdAttr gs_syslinkCmdList[] = {
    { "init", SYSLINK_CMD_SysLinkInit },
    { "deinit", SYSLINK_CMD_SysLinkDeinit },
    { "bootinfo", SYSLINK_CMD_SysLinkBootInfo },
    { "sendcmd", SYSLINK_CMD_SendCmdToWifi },
    { "enabletty", SYSLINK_CMD_EnableTty },
    { "disabletty", SYSLINK_CMD_DisableTty },
    { "attachtty", SYSLINK_CMD_AttachTty },
    { "setloglevel", SYSLINK_CMD_SetLogLevel },
    { "getloglevel", SYSLINK_CMD_GetLogLevel },
    { "wificonnect", SYSLINK_CMD_SetWifiConnect },
    { "wifidisconnect", SYSLINK_CMD_SetWifiDisConnect },
    { "getwifistatus", SYSLINK_CMD_GetWifiStatus },
    { "setledon", SYSLINK_CMD_SetLedOn },
    { "setledoff", SYSLINK_CMD_SetLedOff },
    { "getver", SYSLINK_CMD_GetVer },
    { "getbat", SYSLINK_CMD_GetBatStatus },
    { "setpir", SYSLINK_CMD_SetPirState },
    { "getpir", SYSLINK_CMD_GetPirState },
    { "setsysmode", SYSLINK_CMD_SetSystemMode },
    { "settime", SYSLINK_CMD_SetDateTime },
    { "gettime", SYSLINK_CMD_GetDateTime },

};

static HI_VOID SYSLINK_CMD_DumpHelp(HI_VOID)
{
    HI_U32 funcNum = sizeof(gs_syslinkCmdList) / sizeof(SAMPLE_SYSLINK_CmdAttr);
    for (HI_U32 index = 0; index < funcNum; index++) {
        printf("%s\n", gs_syslinkCmdList[index].testTitle);
    }

    return;
}

static HI_VOID SYSLINK_CMD_DumpArg(HI_U32 argc, HI_CHAR **argv)
{
    MLOGD("argc:%d.\n", argc);
    for (HI_U32 index = 0; index < argc; index++) {
        MLOGD("argv[%d]:%s.\n", index, argv[index]);
    }

    return;
}

HI_U32 SYSLINK_CmdEntry(HI_U32 argc, HI_CHAR **argv)
{
    SYSLINK_CMD_DumpArg(argc, argv);

    if (argc < 1 || argv == HI_NULL) { /* 2:argc */
        SYSLINK_CMD_DumpHelp();
        return HI_SUCCESS;
    }

    HI_U32 argcDown = 0;
    HI_U32 funcNum = sizeof(gs_syslinkCmdList) / sizeof(SAMPLE_SYSLINK_CmdAttr);

    HI_CHAR *argcNew = argc - 1;
    HI_CHAR **argvNew = &argv[1];

    SYSLINK_CMD_DumpArg(argcNew, argvNew);

    HI_U32 index;
    for (index = 0; index < funcNum; index++) {
        if (strcmp(argv[0], (HI_CHAR *)gs_syslinkCmdList[index].testTitle) == 0) {
            if (gs_syslinkCmdList[index].cmdFunc != HI_NULL) {
                (HI_VOID)gs_syslinkCmdList[index].cmdFunc(argcNew, argvNew);
                break;
            }
        }
    }

    if (index >= funcNum) {
        SYSLINK_CMD_DumpHelp();
    }

    return HI_SUCCESS;
}


HI_S32 HI_SYSLINK_CMD_RegOsCmd(HI_VOID)
{
    osCmdReg(CMD_TYPE_EX, "hisyslink", 1, SYSLINK_CmdEntry);

    return HI_SUCCESS;
}


